package com.freemypay.test.并发.线程之间的协作.wait和notifyAll;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 汽车打蜡和抛光演示 （汽车必须先打蜡再抛光，抛光完了再打蜡，一直循环）
 * @author yesixian
 * @date 2018年6月20日
 */
public class WaxOMatic {
	public static void main(String[] args) throws Exception {
		Car car = new Car();
		ExecutorService exec = Executors.newCachedThreadPool();
		exec.execute(new WaxOff(car));
		exec.execute(new WaxOn(car));
		TimeUnit.SECONDS.sleep(5); // Run for a while... 
		exec.shutdownNow(); // Interrupt all tasks
	}
}

class Car {
	/**
	 * 是否打蜡标志：默认 false（未打蜡）
	 */
	private boolean waxOn = false;
	
	/**
	 * 打蜡
	 */
	public synchronized void waxed() {
		waxOn = true; // ready to buff
//		notifyAll();
		notify();
	}
	
	/**
	 * 抛光
	 */
	public synchronized void buffed() {
		 waxOn = false; // ready for another coat of wax
//		 notifyAll();
		 notify();
		 
	}
	
	/**
	 * 抛光前等待打蜡
	 * @throws InterruptedException
	 */
	public synchronized void waitForWaxing() throws InterruptedException {
		while(waxOn == false) {
			 wait();
		}
	}
	
	/**
	 * 打蜡前等待抛光
	 * @throws InterruptedException
	 */
	public synchronized void waitForBuffing() throws InterruptedException {
		while(waxOn == true) {
			wait();
		}
	}
}

/**
 * 打蜡任务
 * @author yesixian
 * @date 2018年6月20日
 */
class WaxOn implements Runnable {
	private Car car;
	
	public WaxOn(Car c) {
		this.car = c;
	}

	@Override
	public void run() {
		try {
			while(!Thread.interrupted()) {
				System.out.println("Wax on!");
				TimeUnit.MILLISECONDS.sleep(200);
				car.waxed();
				car.waitForBuffing();
			}
		} catch (InterruptedException e) {
			System.out.println("Exiting via interrupt");
		}
		System.out.println("Ending wax on task");	
	}
}

/**
 * 抛光任务
 * @author yesixian
 * @date 2018年6月20日
 */
class WaxOff implements Runnable {
	private Car car;
	
	public WaxOff(Car c) {
		this.car = c;
	}
	
	@Override
	public void run() {
			try {
				while(!Thread.interrupted()) {
					car.waitForWaxing();
					System.out.println("Wax Off!");
					TimeUnit.MILLISECONDS.sleep(200);
					car.buffed();
				}
			} catch (InterruptedException e) {
				System.out.println("Exiting via interrupt");
			}
			System.out.println("Ending Wax Off task");
	}
}


